;/*---------------------------------------------------------------------------------
;	$Id: interruptDispatcher.s,v 1.1 2009/06/12 01:52:50 cpy Exp $
;
;	Copyright (C) 2005
;		Dave Murphy (WinterMute)
;
;	This software is provided 'as-is', without any express or implied
;	warranty.  In no event will the authors be held liable for any
;	damages arising from the use of this software.
;
;	Permission is granted to anyone to use this software for any
;	purpose, including commercial applications, and to alter it and
;	redistribute it freely, subject to the following restrictions:
;
;	1.	The origin of this software must not be misrepresented; you
;		must not claim that you wrote the original software. If you use
;		this software in a product, an acknowledgment in the product
;		documentation would be appreciated but is not required.
;	2.	Altered source versions must be plainly marked as such, and
;		must not be misrepresented as being the original software.
;	3.	This notice may not be removed or altered from any source
;		distribution.
;
;	$Log: interruptDispatcher.s,v $
;	Revision 1.1  2009/06/12 01:52:50  cpy
;	6-12
;	Committed on the Free edition of March Hare Software CVSNT Server.
;	Upgrade to CVS Suite for more features and support:
;	http://march-hare.com/cvsnt/
;	
;	Revision 1.1  2009/03/31 05:03:09  administrator
;	
;	Committed on the Free edition of March Hare Software CVSNT Server.
;	Upgrade to CVS Suite for more features and support:
;	http://march-hare.com/cvsnt/
;	
;	Revision 1.10  2007/08/11 06:00:23  wntrmute
;	make nesting really work
;	
;	Revision 1.9  2007/01/10 15:48:27  wntrmute
;	remove unused code
;	
;	Revision 1.8  2006/12/16 09:10:02  wntrmute
;	acknowledge interrupt before calling handler
;	
;	Revision 1.7  2006/04/26 05:11:31  wntrmute
;	rebase dtcm, take __irq_flags and __irq_vector from linker script
;	move arm7 irq vector & irq flags to actual locations
;	
;	Revision 1.6  2006/04/23 18:19:15  wntrmute
;	reworked interrupt code to allow dtcm moving
;	
;	Revision 1.5  2005/12/12 13:01:55  wntrmute
;	disable interrupts on return from user handler
;	
;	Revision 1.4  2005/10/21 22:43:42  wntrmute
;	restore REG_IME on exit from null handler
;	
;	Revision 1.3  2005/09/27 18:21:53  wntrmute
;	safer nested interrupt support
;	
;	Revision 1.2  2005/09/04 16:37:01  wntrmute
;	check for NULL handler
;	
;	Revision 1.1  2005/09/03 17:09:35  wntrmute
;	added interworking aware interrupt dispatcher
;	
;
;---------------------------------------------------------------------------------*/

;#ifdef ARM7
;	.text
;#endif
;
;#ifdef ARM9
;	.section	.itcm,"ax",%progbits
;#endif

    AREA     globals,CODE,READONLY

	IMPORT	irqTable

	EXPORT	IntrMain
;@---------------------------------------------------------------------------------
IntrMain
;@---------------------------------------------------------------------------------
	mov	r3, #0x4000000		;@ REG_BASE

	ldr	r1, [r3, #0x208]	;@ r1 = IME
	str	r3, [r3, #0x208]	;@ disable IME
	mrs	r0, spsr
	stmfd	sp!, {r0-r1,r3,lr}	;@ {spsr, IME, REG_BASE, lr_irq}

	ldr	r1, [r3,#0x210]		;@ REG_IE
	ldr	r2, [r3,#0x214]		;@ REG_IF
	and	r1,r1,r2

;	ldr	r0,=__irq_flags		;@ defined by linker script
	ldr	r0,=(0x04000000-8)		; Bios irq flags on ARM7

	ldr	r2,[r0]
	orr	r2,r2,r1
	str	r2,[r0]

	ldr	r2,=irqTable
;@---------------------------------------------------------------------------------
findIRQ
;@---------------------------------------------------------------------------------
	ldr r0, [r2, #4]
	cmp	r0,#0
	beq	no_handler
	ands	r0, r0, r1
	bne	jump_intr
	add	r2, r2, #8
	b	findIRQ

;@---------------------------------------------------------------------------------
no_handler
;@---------------------------------------------------------------------------------
	str	r1, [r3, #0x0214]	;@ IF Clear
	ldmfd   sp!, {r0-r1,r3,lr}	;@ {spsr, IME, REG_BASE, lr_irq}
	str	r1, [r3, #0x208]	;@ restore REG_IME
	bx lr

;@---------------------------------------------------------------------------------
jump_intr
;@---------------------------------------------------------------------------------
	ldr	r1, [r2]		;@ user IRQ handler address
	cmp	r1, #0
	bne	got_handler
	mov	r1, r0
	b	no_handler
;@---------------------------------------------------------------------------------
got_handler
;@---------------------------------------------------------------------------------

	mrs	r2, cpsr
	bic	r2, r2, #0xdf		;@ \__
	orr	r2, r2, #0x1f		;@ /  --> Enable IRQ & FIQ. Set CPU mode to System.
	msr	cpsr_cxsf,r2

	str	r0, [r3, #0x0214]	;@ IF Clear
	
	push	{lr}
	adr	lr, IntrRet
	bx	r1

;@---------------------------------------------------------------------------------
IntrRet
;@---------------------------------------------------------------------------------
	mov	r3, #0x4000000		;@ REG_BASE
	str	r3, [r3, #0x208]	;@ disable IME
	pop	{lr}

	mrs	r3, cpsr
	bic	r3, r3, #0xdf		;@ \__
	orr	r3, r3, #0x92		;@ /  --> Disable IRQ. Enable FIQ. Set CPU mode to IRQ.
	msr	cpsr_cxsf, r3

	ldmfd   sp!, {r0-r1,r3,lr}	;@ {spsr, IME, REG_BASE, lr_irq}
	msr	spsr_cxsf, r0		;@ restore spsr
	str	r1, [r3, #0x208]	;@ restore REG_IME
	bx lr

  END
